Algorithms FAQ
有一个数组,然后你和另外一个人两头开始取数字。每次你只能取两头里面的某一个数字。让你设计一种策略,使得你取的数字尽可能大
2个的话,先取则赢 3 1 3个的话,中间那个如果比两边和大,则先取必输,否则则先取必赢 2 4 1 4 1 2 1 2 4 4个的话 分成两组,奇数位一组,偶数位一组,那组大则先取哪组,先取必赢 1 2 3 4
现在可以推出规律了,分成两组,奇数位一组,偶数位一组,看哪组和最大,最大的话先取哪组,然后一直保持取那一组的数即可
比如 1 2 3 4 5 6 偶数位和比较大,先取6 ,对方只能取1或者5,取1你就取2,取5你就取4,保持对方取奇数位上的就行了
- 静下来,从2,3,4,5,试试,就找出规律啦
- 动态规划问题.
找最大和Max-gain(1,n),等价于找“比对手最多赢多少”max-diff(1,n) + max-diff(i,j) 为 1, A[i] - max-diff(i+1,j) 2, A[j] - max=diff(i,j-1) 的两个最大值边界— max-diff(i,i) = A[i] only one left, and it's A's turn.
用DP…反着做,O(N2)
p(i,j) = max { A[i] + min {p(i+2,j), p(i+1,j-1)}, A[j] + min {p(i,j-2), p(i+1,j-1)} }
Pascal’s Triangle
/* time complexity: O(n^2), space: O(n) */ void printPascal(int n) { int arr[n]; int i, j, k; for(i = 0; i < n; ++i){ arr[i] = 1; for(j = i; j > 1; --j) arr[j - 1] += arr[j - 2]; for(k = 0; k <= i; ++k) printf("%d ",arr[k]); printf("\n"); } } /* time: O(n^2), space: O(1) */ /* C(line, i) = line * .. *(line - i - 1) / i! C(line, i+1) = line * .. * (line - i) / (i + 1)! C(line, i+1) = C(line, i) * (line - i) / (i + 1) */ void printPascal(int n) { int arr[n]; int i, j; int C; for(i = 0; i < n; ++i){ C = 1; for(j = 0; j <=i ; ++j){ printf("%d ", C); C = C * (i - j) / (j + 1); } printf("\n"); } }